home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Tool Chest / Testing & Debugging / Mac OS Development Toolkit / Automation Essentials 2.3.0 / Host Automation Folder / Clouseau libs / MemoryCP.lib < prev    next >
Encoding:
Text File  |  1998-03-19  |  61.3 KB  |  1,892 lines  |  [TEXT/MPS ]

  1. #########################################################################
  2. #########################################################################
  3. ##                     Copyright © Apple Computer, Inc. 1993-1998
  4. ##                                All rights reserved
  5. #########################################################################
  6. #########################################################################
  7. #    
  8. #    Library:        MemoryCP.lib
  9. #    
  10. #    Version:        2.1.5
  11. #    
  12. #    Description:
  13. #        Sets any section of the Memory Control Panel to any possible value.
  14. #
  15. #        This is a complex set of tasks, for several reasons:
  16. #        a)    Most of the items in the window are not VU visible and they have 
  17. #            to be read by direct screen access. This especially applies to 
  18. #            all the numbers. The VU visible items can not be selected by VU 
  19. #            because their locations are horizontally offset by -89 pixels.
  20. #            THIS HAS BEEN FIXED IN VU 2.1!!!!!
  21. #        b)    The window size and contents change, depending on which features 
  22. #            are available on the target CPU. For example, some CPUs have a 
  23. #            32-bit Addressing section, others do not. The sections below 
  24. #            a "variable" section move up or down to make room.
  25. #        c)    Setting some sections affects the possible settings of others.
  26. #            The sections must be set in a particular order to take this
  27. #            into account. Some examples:
  28. #            32-Bit Addressing affects the maximum VM amount.
  29. #            RAM Disk affects the minimum VM and maximum Disk Cache amounts.
  30. #            Use Defaults affects all other sections.
  31. #        d)    The caller may want to set every section, only one section,
  32. #            or a subset of all sections, and should not have to wait or
  33. #            supply "empty" values for the other sections.
  34. #        e)    Some requests can only be fulfilled on a "close enough" basis.
  35. #            If the caller asks for a RAM Disk amount of 1024K, there may be
  36. #            enough RAM, but the actual settings possible by using the slider
  37. #            may be 1120K on the low side and 1440K on the high side. In such
  38. #            cases close enough is considered good enough. However, the caller
  39. #            must be the final arbiter of this. For comparison, the actual 
  40. #            settings of each section are returned with the desired settings  
  41. #            but no error is generated.
  42. #        f)    After all this, the architecture must support the addition of 
  43. #            new sections not currently implemented. For example, the PowerPC
  44. #            Memory Control Panel contains a Memory Manager section not found 
  45. #            on any previous CPU. Adding this was relatively easy since
  46. #            the architecture already supported movable sections. 
  47. #        
  48. #        The main task calculates the locations of all sections, and stores 
  49. #        these values. Each section has its own task which uses the stored 
  50. #        locations to figure out where to look and where to click. The main 
  51. #        task calls each one in turn, then collects and returns the results.
  52. #    
  53. #    
  54. #    Contains:
  55. #        memoryCP_getWindowItems()
  56. #        memoryCP_setDiskCache()
  57. #        memoryCP_setModMemMgr()
  58. #        clickVMOnButton()
  59. #        memoryCP_setVM()
  60. #        memoryCP_set32Bit()
  61. #        memoryCP_setRAMDisk()
  62. #        memoryCP_setUseDefaults()
  63. #    
  64. #    History:
  65. #        Date:        By:        Changes:
  66. #        01/12/93    SBR        Created
  67. #        05/29/93    SBR        Added Heap Style section for PowerPC, see 
  68. #                            memoryCP_setModMemMgr().
  69. #        06/15/93    SBR        Added v_level to reporting, set debugging reporting 
  70. #                            to v_level + 1.
  71. #        07/20/93    SBR        Removed Heap Style section. Its User Interface status 
  72. #                            is uncertain.
  73. #        09/01/93    SBR        Moved debugging "if" to after the return values are 
  74. #                            defined.
  75. #        09/07/93    SBR        Added section for PowerPC, see memoryCP_setModMemMgr().
  76. #        11/27/93    SBR        Cleaned up comments and formatting, small bug fixes.
  77. #        03/10/95    SBR        Modified for exclusive use with VU 2.1 (VU is at 
  78. #                            2.1a3e12 now).
  79. #                            Changed task from memoryCP_setNewMemMgr() to 
  80. #                            memoryCP_setModMemMgr().
  81. #        09/27/96    BRL/MSO    Updated copyright header
  82. #                            Use SPEC exception handling method (ExceptionHandling.lib)
  83. #        01/21/97    SBR        Deleted older exception code and comments.
  84. #        03/20/97    SBR        Updated for Mac OS 8.0.
  85. #        02/19/98    SBR        Updated for Mac OS 8.1, removed code for non-GM 8.0.
  86. #        03/10/98    CTE        Removed remainder of code for non-GM 8.0.
  87. #    
  88. #########################################################################
  89. #########################################################################
  90. Libraries    
  91.     "Additions.lib",
  92.     "Clouseau.lib", 
  93.     "ReadGeneva9Numbers.lib",
  94.     "Report.lib", 
  95.     "TargetControl.lib",
  96.     "VUAid.lib",
  97.     "ExceptionHandling.lib";
  98.     
  99. #########################################################################
  100. #    task            MemoryCP()
  101. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  102. #    Description:    The user-callable task, divides up the work among all the internal tasks.
  103. #    Parameters:    
  104. #        myMems:
  105. #            There are 3 basic ways to use this parameter:
  106. #            (1)    Set the entire Memory CP by putting an assoc() list into myMems:
  107. #                myMems :=    {    {diskCacheList}, 
  108. #                                {modMemMgrList},
  109. #                                {vmList}, 
  110. #                                {addr32BitList}, 
  111. #                                {ramDiskList},
  112. #                                {miscList}
  113. #                            };
  114. #                All items in myMems are optional. If an item is not in the list it is 
  115. #                ignored. The items contain IDs so they can be in any order.
  116. #                
  117. #                WARNING: Clicking 'Use Default' may change values you want to ignore. For
  118. #                    example, it changes the disk cache size, turns off 32-Bit and RAM Disk, 
  119. #                    and sets the VM Backing Store volume to the startup volume. This task 
  120. #                    currently does not restore any values after clicking 'Use Default'.
  121. #                
  122. #                WARNING: If the RAM Disk holds any items you can not change its settings. 
  123. #                    This task logs an error message if you attempt any action with the RAM 
  124. #                    Disk when the Memory CP has disabled its controls. 
  125. #                
  126. #                diskCacheList:
  127. #                    {    'dc',
  128. #                            the second item is one of the following:
  129. #                        'xK':        (x > 0) the value in KB
  130. #                        'random':    choose from the list of 23 values
  131. #                                    (see dcValues in memoryCP_setDiskCache)
  132. #                        'read':        return the value present before changes
  133. #                        'no change':    recover from Use Defaults (not implemented)
  134. #                        '':            ignore this section
  135. #                    }
  136. #        
  137. #                modMemMgrList:
  138. #                    {    'mm',
  139. #                            the second item is one of the following:
  140. #                        'On':            click On if not already selected
  141. #                        'Off':            click Off if not already selected
  142. #                        'random':        click On or Off randomly
  143. #                        'read':            return the value present before changes
  144. #                        'no change':    recover from Use Defaults (not implemented)
  145. #                        '':            ignore this section
  146. #                    }
  147. #    
  148. #                vmList:
  149. #                    {    'vm',
  150. #                            the second item in vmList is itself a list
  151. #                        {
  152. #                                the first item is one of the following:
  153. #                            'On':    click On if not already selected
  154. #                            'xM':    (x > 0) click On, set the value to xM
  155. #                            'x%':    (0 <= x <= 100) click On, use up x % of available
  156. #                            'Off':    click Off if not already selected
  157. #                            'Min':    set VM to minimum
  158. #                            'Max':    set VM to maximum (available on disk - 1M)
  159. #                            'auto': let Memory CP automatically choose value by 
  160. #                                    turning VM Off then On after setting all others
  161. #                            'random':        choose from minimum to maximum
  162. #                            'read':            return the value present before changes
  163. #                            'no change':    recover from Use Defaults (not implemented)
  164. #                            '':            ignore this section
  165. #                            
  166. #                            ,
  167. #                            
  168. #                                the second item is one of the following:
  169. #                            '':    ignore bs volume setting (currently the only choice)
  170. #                            bs:    the string name of the backing store volume (not yet)
  171. #                        }
  172. #                    }
  173. #        
  174. #                addr32BitList:
  175. #                    {    '32',
  176. #                            the second item is one of the following:
  177. #                        'On':        click On if not already selected 
  178. #                        'Off':        click Off if not already selected
  179. #                        'random':    click On or Off randomly
  180. #                        'read':        return the value present before changes
  181. #                        'no change': recover from Use Defaults (not implemented)
  182. #                        '':            ignore this section
  183. #                    }
  184. #        
  185. #                ramDiskList:
  186. #                    {    'rd',
  187. #                            the second item is one of the following:
  188. #                        'xK':    (0 <= x <= 32767) size in KB (click On or Off as needed)
  189. #                        'x%':    (0 <= x <= 100) set to % of 125 pixel positions (fast)
  190. #                        'x%!':    (0 <= x <= 100) set to % of max - min (slow, accurate)
  191. #                        'Off':    click Off
  192. #                        'Min':    set to minimum size
  193. #                        'Max':    set to maximum size
  194. #                        'random':    drags slider from min to to random(0,125) with 0 = Off
  195. #                        'read':        return the value present before changes
  196. #                        'VMOn':     set size just high enough to allow use of VM (not yet)
  197. #                        'no change': recover from Use Defaults (not implemented)
  198. #                        '':            ignore this section
  199. #                    }
  200. #            
  201. #                useDefaultsList:
  202. #                    {    'ud',
  203. #                            'click'    :    click Use Defaults before setting other sections
  204. #                        '':                ignore this section
  205. #                    }
  206. #        
  207. #            (2) Attempt to default to standard system 7.0-7.1 settings, equivalent to 
  208. #                    SetMemoryCP({ { 'vm',{ 'Off','' } },{ 'ud', 'click' } }). Usually this results 
  209. #                    in Disk Cache at default, VM Off, 24-bit, RAM Disk Off. However, in some
  210. #                    systems 32-Bit is always On, and the warnings above always apply.
  211. #            (3) Return the current settings by putting the string 'readOnly' in myMems.
  212. #            verbosity_level: verbosity level to push during this script
  213. #            reset_target: calls reset() at the beginning
  214. #    Returns: { error, previousSettings, askedSettings, currentSettings} 
  215. #                error: 0 for no error, non-zero for error
  216. #                previousSettings: the settings before making any changes
  217. #                askedSettings: myMems
  218. #                currentSettings: may not be the same as asked Settings
  219. #    Examples:
  220. #        (1)    saveMemory := MemoryCP({{ 'dc','256K' },{ 'vm',{ '27M','' } },{ '32','On' },
  221. #                                            { 'rd','1024K'} }, 3);
  222. #            ...
  223. #            MemoryCP(saveMemory[2]);
  224. #        (2)    MemoryCP({});
  225. #        (3)    theMemory := MemoryCP('readOnly');
  226. #    Assumptions:    Uses VU 2.1 and VUAid 2.1. Bit depth is 1,2,4,8,16, or 32.
  227. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  228. #    History:
  229. #        01/12/93    SBR        Created
  230. #        04/09/95    SBR        Closes the control panel when finished.
  231. #        09/27/96    BRL/MSO    Added SPEC exception handling
  232. #########################################################################
  233. task MemoryCP    (    myMems := {
  234.                         #mydc := 
  235.                             {'dc','96K'},
  236.                         #mymm := 
  237.                             {'mm','On'},
  238.                         #myvm := 
  239.                             {'vm',{'Off',''}},
  240.                         #my32 := 
  241.                             {'32','On'},
  242.                         #myrd := 
  243.                             {'rd','Off'},
  244.                         #myud := 
  245.                             {'ud','click'},
  246.                         #myq := 
  247.                             'quick'
  248.                     }
  249.                             
  250.                 #THE LINES BELOW ARE FOR DEVELOPMENT AND ARE NORMALLY COMMENTED OUT >>>>
  251. #                    ,
  252. #                    repeat_for := 1, #SBR dev code
  253. #                    make_alias := false,
  254. #                    reset_target := false,
  255. #                    tracer := false
  256.                 # THE LINES ABOVE ARE FOR DEVELOPMENT AND ARE NORMALLY COMMENTED OUT <<<<
  257.  
  258.                     ,v_level := 4
  259.                 )
  260. begin
  261.     global gmcp;    # Global Memory Control Panel (gmcp) is an assoc list of visible sections
  262.     
  263.     VUAidReturnLongIntegers();
  264.     
  265.     #THE LINES BELOW ARE FOR DEVELOPMENT AND ARE NORMALLY COMMENTED OUT >>>>
  266. #        RPushVerbosity(2);
  267. #        
  268. #        if typeOf(v_level) = 'string'
  269. #        begin
  270. #            v_level := strToNum(v_level);
  271. #            rPushVerbosity(v_level);
  272. #            v_level := 4;
  273. #        end;
  274. #        RStatus('memoryCP script',v_level);
  275. #        if reset_target 
  276. #            key_eq('w');    #SBR dev stuff
  277. #        if isUndefined(myMems)
  278. #            myMems := { mydc, mymm, myvm, my32, myrd, myud, myq };
  279. #        if make_alias
  280. #            alias_control_panel('Memory');
  281.     #THE LINES ABOVE ARE FOR DEVELOPMENT AND ARE NORMALLY COMMENTED OUT <<<<
  282.             
  283.     saveSpeed := MouseSpeed(0);
  284.     
  285. ##    OPEN MEMORY CP
  286.     if not memoryCP_getWindowItems()
  287.         return { -1, {}, {}, {}};
  288.         
  289.     #THE LINES BELOW ARE FOR DEVELOPMENT AND ARE NORMALLY COMMENTED OUT >>>>
  290. #        if card myrd = 3
  291. #        begin
  292. #            specialRAMDisk := true;
  293. #            theRDValue := myrd[1];
  294. #            theRDInterval := myrd[2];
  295. #            theRDMax := myrd[3];
  296. #        end;
  297. #        for iterations := 1 to repeat_for
  298. #        begin
  299. #            isVUAidInstalled();
  300. #            if specialRAMDisk
  301. #            begin
  302. #                theRDValue := theRDValue + theRDInterval;
  303. #                if theRDValue > theRDMax
  304. #                    repeat_for := 1;
  305. #                myMems[5] := { 'rd',"{numToStr(theRDValue)}K" };
  306. #                #println "Begin setting the Memory Control Panel with {myMems[5]}";
  307. #            end;
  308. #            else
  309. #            begin
  310. #                println "Begin setting the Memory Control Panel";
  311. #            end;
  312. #            startTime := _Match([time]);
  313. #            #println "iteration {iterations}";
  314.     #THE LINES ABOVE ARE FOR DEVELOPMENT AND ARE NORMALLY COMMENTED OUT <<<<
  315.     
  316.     quickSet := false;
  317.     if myMems = 'readOnly'
  318.     begin
  319.         newDCValue := 'read';
  320.         newMMValue := 'read';
  321.         newVMValue := 'read';
  322.         new32Value := 'read';
  323.         newRDValue := 'read';
  324.         newUDValue := '';
  325.     end;
  326.     else begin
  327.         if not myMems             #default settings for sys 7.0-7.1-7.5 (they may differ)
  328.             myMems := { { 'vm', { 'Off', '' } }, {'ud', 'click'} };
  329.         newDCValue := assoc('dc', myMems);
  330.         newVMValue := assoc('vm', myMems);         # get the setting request for each section
  331.         newMMValue := assoc('mm', myMems);
  332.         new32Value := assoc('32', myMems);
  333.         newRDValue := assoc('rd', myMems);
  334.         newUDValue := assoc('ud', myMems);
  335.         if isMember('quick',myMems)
  336.             quickSet := true;
  337.     end;
  338.     
  339.     if not quickSet        # quickSet false: read pertinent values before setting
  340.     begin
  341.         if newVMValue 
  342.         begin
  343.             if typeOf( newVMValue ) = 'list'
  344.                 previousVM := 'readMe';
  345.             if typeOf( newVMValue ) = 'string'
  346.                 if newVMValue <> 'read'
  347.                     previousVM := 'readMe';
  348.             if previousVM = 'readMe'
  349.                 previousVM := memoryCP_setVM('read')[3];         #read VM before setting 32-Bit
  350.         end;
  351.         if newDCValue and newDCValue <> 'read'
  352.             previousDC := memoryCP_setDiskCache('read')[3];     #read DC before setting RAM Disk
  353.  
  354.         if newUDValue
  355.         begin
  356.             if newRDValue and newRDValue <> 'read'
  357.                 previousRD := memoryCP_setRAMDisk('read')[3];    #read RD, 32, and MM
  358.             if new32Value and new32Value <> 'read'
  359.                 previous32 := memoryCP_set32Bit('read')[3];     #before clicking Use Defaults
  360.             if newMMValue and newMMValue <> 'read'
  361.                 previousMM := memoryCP_setModMemMgr('read')[3]; 
  362.         end;
  363.     end;
  364.     
  365.     # CAUTION: The modules must execute in this order because of dependencies between sections
  366.     
  367.     temp1 := memoryCP_setUseDefaults(newUDValue);
  368.     if temp1[4] 
  369.         RStatus(temp1[4],v_level);
  370.     
  371.     temp2 := memoryCP_set32Bit(new32Value);
  372.     if temp2[2] and previous32 
  373.         temp2[2] := previous32;
  374.     if temp2[4] 
  375.         RStatus(temp2[4],v_level);
  376.     
  377.     temp3 := memoryCP_setRAMDisk(newRDValue);
  378.     if temp3[2] and previousRD 
  379.         temp3[2] := previousRD;
  380.     if temp3[4] 
  381.         RStatus(temp3[4],v_level);
  382.         
  383.     temp4 := memoryCP_setDiskCache(newDCValue);
  384.     if temp4[2] 
  385.         temp4[2] := previousDC;
  386.     if temp4[4] 
  387.         RStatus(temp4[4],v_level);
  388.  
  389.     temp5 := memoryCP_setVM(newVMValue);
  390.     if temp5[2] 
  391.         temp5[2] := previousVM;
  392.     if temp5[4] 
  393.         RStatus(temp5[4],v_level);
  394.     
  395.     temp6 := memoryCP_setModMemMgr(newMMValue);
  396.     if temp6[2] 
  397.         temp6[2] := previousMM;
  398.     if temp6[4] 
  399.         RStatus(temp6[4],v_level);
  400.  
  401.     previousSettings := 
  402.         {
  403.             { 'dc', temp4[2] },
  404.             { 'mm', temp6[2] },
  405.             { 'vm', temp5[2] },
  406.             { '32', temp2[2] },
  407.             { 'rd', temp3[2] },
  408.             { 'ud', temp1[2] }
  409.         };
  410.     askedSettings :=
  411.         {
  412.             { 'dc', newDCValue },
  413.             { 'mm', newMMValue },
  414.             { 'vm', newVMValue },
  415.             { '32', new32Value },
  416.             { 'rd', newRDValue },
  417.             { 'ud', newUDValue }
  418.         };
  419.     currentSettings :=
  420.         {
  421.             { 'dc', temp4[3] },
  422.             { 'mm', temp6[3] },
  423.             { 'vm', temp5[3] },
  424.             { '32', temp2[3] },
  425.             { 'rd', temp3[3] },
  426.             { 'ud', temp1[3] }
  427.         };
  428.         
  429.     error := temp1[1] or temp2[1] or temp3[1] or temp4[1] or temp5[1];
  430.     VUAid('quit');
  431.  
  432.     #THE LINES BELOW ARE FOR DEVELOPMENT AND ARE NORMALLY COMMENTED OUT >>>>
  433. #            #if R_BeVerbose(v_level)            #for diagnostics
  434. #            begin
  435. #                println "previous MemoryCP:";
  436. #                println '{';
  437. #                for i := 1 to (card previousSettings) - 1
  438. #                    println previousSettings[i], ',';
  439. #                println previousSettings[card previousSettings];
  440. #                println '{';
  441. #    
  442. #                println "asked MemoryCP:";
  443. #                println '{';
  444. #                for i := 1 to (card askedSettings) - 1
  445. #                    println askedSettings[i], ',';
  446. #                println askedSettings[card askedSettings];
  447. #                println '{';
  448. #    
  449. #                println "current MemoryCP:";
  450. #                println '{';
  451. #                for i := 1 to (card currentSettings) - 1
  452. #                    println currentSettings[i], ',';
  453. #                println currentSettings[card currentSettings];
  454. #                println '{';
  455. #            end;
  456. #            
  457. #            print 'End setting the Memory Control Panel ';
  458. #            println time_str(time_sub(_Match([time]), startTime));
  459. #            println { error, previousSettings, askedSettings, currentSettings} ;
  460. #        end;
  461.     #THE LINES ABOVE ARE FOR DEVELOPMENT AND ARE NORMALLY COMMENTED OUT <<<< 
  462.  
  463.     key_eq('w');
  464.     MouseSpeed(saveSpeed);
  465.     return { error, previousSettings, askedSettings, currentSettings};
  466. end;            # MemoryCP
  467.  
  468. #########################################################################
  469. #    Task            memoryCP_getWindowItems( v_level )
  470. #    Description:    Collects data used in the Memory CP. These include the window 
  471. #                    relative locations of the sections and the corrected coordinates 
  472. #                    of the visible controls. Here are all possible sections as of 
  473. #                    08/25/94. In practice gmcp is smaller, because no Macintosh has 
  474. #                    both Modern Memory Manager and 32-Bit Addressing sections.
  475. #                    global gmcp :=
  476. #                        {
  477. #                            { 'win',{ windowRect } },
  478. #                            { 'dc',{ dcLeftTop } },
  479. #                            { 'mm',{ mmLeftTop,[mmOff],[mmOn] } },
  480. #                            { 'vm',{ vmLeftTop,[vmOff],[vmOn] } },
  481. #                            { '32',{ 32LeftTop,[32Off],[32On] } },
  482. #                            { 'rd',{ rdLeftTop,[rdSlider],[rdOff],[rdOn] } },
  483. #                            { 'ud',{ udLeftTop,[ud] } } }
  484. #                        };
  485. #    Parameters:        v_level
  486. #    Returns:        successful: true
  487. #                    unsuccessful: false
  488. #    History:
  489. #        01/23/93    SBR            Created
  490. #        05/29/93    SBR            Added New Heap section for PowerPC
  491. #        07/20/93    SBR            Removed Heap Style section. Its User Interface status is uncertain.
  492. #        09/07/93    SBR            Added Memory Manager section for PowerPC.
  493. #        04/06/94    GKratzer    Changed verbosity level for open_control_panel call to 4.
  494. #        09/27/96    BRL/MSO        Added SPEC exception handling
  495. #        03/20/97    SBR            Changed v_level to 4.
  496. #                                Pre-calculate left-top values for sections.
  497. #                                Special-case item locations for 8.0.
  498. #                                Fixed Radar 1272363.
  499. #        02/23/98    SBR            Changed version match from /v7.≈/ to /v[0-9].≈/ .
  500. #                                Added case 48 for Mac OS 8.1 item list.
  501. #########################################################################
  502. Task memoryCP_getWindowItems( v_level := 4 )
  503. begin
  504.     global gmcp;
  505.     
  506.     if not isUndefined(gmcp)            # skip to save time if it looks like the same window
  507.         if _MatchBoolean( [window t:'Memory' o:1 b:assoc('win',gmcp)[1]], true)
  508.             return true;
  509.  
  510.     RStatus('Opening the Memory control panel.',v_level);
  511.  
  512.     if not (_MatchBoolean([window t:'Memory' o:1]) AND _MatchBoolean([application t:'Finder']))
  513.         open_control_panel('Memory',,4);
  514.     
  515.  
  516.     # Drag Memory CP to the main screen only if a portion is hidden (Radar 1272363).
  517.     # Use the window rectangle (r:) trait for this comparison
  518.     try 
  519.         match [window t:'Memory' o:1 r:?windowRect];
  520.     catch theError
  521.         ExceptionDispatcher(theError,,{"match 1 in memoryCP_getWindowItems", {v_level}});
  522.  
  523.     screenRect := _Match([screen m:true], true).r;
  524.     if         ((windowRect[1] < screenRect[1]) or 
  525.             (windowRect[2] < screenRect[2]) or
  526.             (windowRect[3] > screenRect[3]) or
  527.             (windowRect[4] > screenRect[4]))
  528.     begin
  529.         _Drag([window t:'Memory' o:1], 'a', {5,20});
  530.     end;
  531.     
  532.  
  533.     # Use the window bounds (b:) trait to work inside the window.
  534.     try 
  535.         match [window t:'Memory' o:1 b:?windowRect];
  536.     catch theError
  537.         ExceptionDispatcher(theError,,{"match 2 in memoryCP_getWindowItems", {v_level}});
  538.  
  539.     try 
  540.         match [control t:$cN o:$cO s:$cS e:$cE r:$cR w:1];
  541.     catch theError
  542.         ExceptionDispatcher(theError,,{"memoryCP_getWindowItems 2", {v_level}});
  543.  
  544.     udOrdinal := cO[isMember('Use Defaults',cN)];    # which ordinality is Use Defaults?
  545.     RStatus("Use Defaults is ordinality {udOrdinal}.",v_level);
  546.     RStatus("MemCP version {_Match([staticText t:/v[0-9].≈/])} .",v_level);
  547.     switch udOrdinal 
  548.     begin
  549.         case 48:         # System 8.1
  550.         begin
  551.             # assign empty descriptors for controls until real one is found
  552.             mItems :=     {    
  553.                 [],     # o:(0) Modern Memory Manager 'Off'    not in this version
  554.                 [],     # o:(0) Modern Memory Manager 'On'    not in this version
  555.                 [],     # o:43 RAM Disk 'RAM Disk Slider' (boring...)
  556.                 [],     # o:45 RAM Disk 'Off'
  557.                 [],     # o:46 RAM Disk 'On'
  558.                 [],        # o:48 'Use Defaults'
  559.                 [],        # o:(0) 32-Bit 'Off'                not in this version
  560.                 [],     # o:(0) 32-Bit 'On'                 not in this version
  561.                 [],     # o:53 VM 'Off'
  562.                 [],        # o:54 VM 'On'
  563.                 []        # o:52 VM 'Select Hard Disk:'
  564.             };
  565.             
  566.             #Ordinality within the MemCP window of all items in mItems, by index
  567.             mItemsOrdinals := { 0, 0, 43, 45, 46, 48, 0, 0, 53, 54, 52 };
  568.  
  569.         end;
  570.         case 49:         # System 8.0
  571.         begin
  572.             # assign empty descriptors for controls until real one is found
  573.             mItems :=     {    
  574.                 [],     # o:(0) Modern Memory Manager 'Off'    not in this version
  575.                 [],     # o:(0) Modern Memory Manager 'On'    not in this version
  576.                 [],     # o:44 RAM Disk 'RAM Disk Slider' (boring...)
  577.                 [],     # o:46 RAM Disk 'Off'
  578.                 [],     # o:47 RAM Disk 'On'
  579.                 [],        # o:49 'Use Defaults'
  580.                 [],        # o:(0) 32-Bit 'Off'                not in this version
  581.                 [],     # o:(0) 32-Bit 'On'                 not in this version
  582.                 [],     # o:54 VM 'Off'
  583.                 [],        # o:55 VM 'On'
  584.                 []        # o:53 VM 'Select Hard Disk:'
  585.             };
  586.             
  587.             #Ordinality within the MemCP window of all items in mItems, by index
  588.             mItemsOrdinals := { 0, 0, 44, 46, 47, 49, 0, 0, 54, 55, 53 };
  589.  
  590.         end;
  591.         case 56:         # System 7.6
  592.         begin
  593.             # assign empty descriptors for controls until real one is found
  594.             mItems :=     {    
  595.                 [],     # o:(0) Modern Memory Manager 'Off'    not in this version
  596.                 [],     # o:(0) Modern Memory Manager 'On'    not in this version
  597.                 [],     # o:52 RAM Disk 'Slide Me Baby!'
  598.                 [],     # o:54 RAM Disk 'Off'
  599.                 [],     # o:55 RAM Disk 'On'
  600.                 [],        # o:56 'Use Defaults'
  601.                 [],        # o:(0) 32-Bit 'Off'                not in this version
  602.                 [],     # o:(0) 32-Bit 'On'                 not in this version
  603.                 [],     # o:59 VM 'Off'
  604.                 []        # o:60 VM 'On'
  605.             };
  606.             
  607.             #Ordinality within the MemCP window of all items in mItems, by index
  608.             mItemsOrdinals := { 0, 0, 52, 54, 55, 56, 0, 0, 59, 60 };
  609.             
  610.         end;
  611.         case 54:         # System 7.1.2, 7.5, etc.
  612.         begin
  613.             # assign empty descriptors for controls until real one is found
  614.             mItems :=     {    
  615.                 [],     # o:49 Modern Memory Manager 'Off'
  616.                 [],     # o:50 Modern Memory Manager 'On'
  617.                 [],     # o:51 RAM Disk 'Slide Me Baby!'
  618.                 [],     # o:52 RAM Disk 'Off'
  619.                 [],     # o:53 RAM Disk 'On'
  620.                 [],        # o:54 'Use Defaults'
  621.                 [],        # o:55 32-Bit 'Off'
  622.                 [],     # o:56 32-Bit 'On'
  623.                 [],     # o:57 VM 'Off'
  624.                 []        # o:58 VM 'On'
  625.             };
  626.             
  627.             #Ordinality within the MemCP window of all items in mItems, by index
  628.             mItemsOrdinals := { 49, 50, 51, 52, 53, 54, 55, 56, 57, 58 };
  629.  
  630.         end;
  631.         case 45:         # System 7.0.1, 7.1, 7.1.1
  632.         begin
  633.             # assign empty descriptors for controls until real one is found
  634.             mItems :=     {    
  635.                 [],     # o:(0) Modern Memory Manager 'Off'    not in this version
  636.                 [],     # o:(0) Modern Memory Manager 'On'    not in this version
  637.                 [],     # o:42 RAM Disk 'Slide Me Baby!'
  638.                 [],     # o:43 RAM Disk 'Off'
  639.                 [],     # o:44 RAM Disk 'On'
  640.                 [],        # o:45 'Use Defaults'
  641.                 [],        # o:46 32-Bit 'Off'
  642.                 [],     # o:47 32-Bit 'On'
  643.                 [],     # o:48 VM 'Off'
  644.                 []        # o:49 VM 'On'
  645.             };
  646.             
  647.             #Ordinality within the MemCP window of all items in mItems, by index
  648.             mItemsOrdinals := { 0, 0, 42, 43, 44, 45, 46, 47, 48, 49 };
  649.     
  650.         end;
  651.         default:
  652.         begin
  653.             RError("Can not identify this Memory CP version:",1);
  654.             RError("MemCP version {_Match([staticText t:/v7.≈/])} .",1);
  655.             RError("Use Defaults is ordinality {udOrdinal}, not 45, 54, 56, or 58.",1);
  656.             RError("System {_Match([system])}",1);
  657.             RError("Please be sure you are using Virtual User 2.1.4a1e4 or later.",1);
  658.             return false;
  659.         end;
  660.     end;
  661.     
  662.     #Index (not ordinality) of all possible items in mItems
  663.     mmOff := 1;    mmOn := 2;
  664.     rdSlider := 3;    rdOff := 4;    rdOn := 5;
  665.     useDef := 6;
  666.     b32Off := 7;    b32On := 8;
  667.     vmOff := 9;        vmOn := 10;        vmVolume := 11;
  668.  
  669.     mItemsCount := card mItems;
  670.     for i := 1 to mItemsCount                        # fill each item which has a visible control 
  671.     begin
  672.         j := isMember(mItemsOrdinals[i], cO);
  673.         if j
  674.         begin
  675.                 # 09/18/94 SBR: Removed for VU 2.1, it can retrieve them correctly
  676. #                tempR := offset_list(cR[j],{-89, 0});    # remove Control Panel window horizontal offset
  677.             mItems[i] := [control t:cN[j] o:cO[j] s:cS[j] e:cE[j] r:cR[j]];
  678.         end;
  679.     end;
  680.     
  681.      #save VU memory space by clearing large lists
  682.     cN := undefined; cO := undefined; cS := undefined; cE := undefined; cR := undefined;
  683.     
  684.     dcHeight := 54;                # pixel height of Memory CP sections
  685.     mmHeight := 64;
  686.     vmHeight := 95;
  687.     b32Height := 64;
  688.     rdHeight := 85;
  689.  
  690.     dcLeftTop := {windowRect[1],windowRect[2]};        #disk cache is always there
  691.     gmcp := 
  692.     { 
  693.         { 'win',{ windowRect } },
  694.         { 'dc',{ dcLeftTop } }
  695.     };
  696.     gmcpNextIndex := 3;        # VU 2.1 appends if assigning to an index of (card theList) + 1
  697.             
  698.     if mItems[mmOn]
  699.     begin
  700.         mmLeftTop := offset_list(dcLeftTop, {0,dcHeight});
  701.         gmcp[gmcpNextIndex] := { 'mm',{ mmLeftTop,mItems[mmOff],mItems[mmOn] } } ;
  702.         gmcpNextIndex := gmcpNextIndex + 1;
  703.     end;
  704.     else begin
  705.         mmLeftTop := dcLeftTop;
  706.         mmHeight := dcHeight;
  707.     end;
  708.     
  709.     if mItems[vmOn]
  710.     begin
  711.         vmLeftTop := offset_list(mmLeftTop, {0,mmHeight});
  712.         gmcp[gmcpNextIndex] := { 'vm',{ vmLeftTop,mItems[vmOff],mItems[vmOn] } };
  713.         gmcpNextIndex := gmcpNextIndex + 1;
  714.     end;
  715.     else begin
  716.         vmLeftTop := mmLeftTop;
  717.         vmHeight := mmHeight;
  718.     end;
  719.     
  720.     if mItems[b32On]
  721.     begin
  722.         b32LeftTop := offset_list(vmLeftTop, {0,vmHeight});
  723.         gmcp[gmcpNextIndex] := { '32',{ b32LeftTop,mItems[b32Off],mItems[b32On] } };
  724.         gmcpNextIndex := gmcpNextIndex + 1;
  725.     end;
  726.     else begin
  727.         b32LeftTop := vmLeftTop;
  728.         b32Height := vmHeight;
  729.     end;
  730.     
  731.     if mItems[rdOn]
  732.     begin
  733.         rdLeftTop := offset_list(b32LeftTop, {0,b32Height});
  734.         gmcp[gmcpNextIndex] := { 'rd',{ rdLeftTop,mItems[rdSlider],mItems[rdOff],mItems[rdOn] } };
  735.         gmcpNextIndex := gmcpNextIndex + 1;
  736.     end;
  737.     else begin
  738.         rdLeftTop := b32LeftTop;
  739.         rdHeight := b32Height;
  740.     end;
  741.     
  742.     udLeftTop := offset_list(rdLeftTop, {0,rdHeight});
  743.     gmcp[gmcpNextIndex] := { 'ud',{ udLeftTop,mItems[useDef] } };
  744.     
  745.     RStatus( "memoryCP_getWindowItems gmcp = {gmcp}", v_level);
  746.     return true;
  747. end;
  748.  
  749.  
  750. #########################################################################
  751. #    Task            memoryCP_setDiskCache( newDC , v_level )
  752. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  753. #    Description:    Sets the Disk Cache section of the Memory CP. 
  754. #    Parameters:        newDC:        see MemoryCP()
  755. #                    v_level:    verbosity level
  756. #    Returns:        newDC contains a false value: { 0,'','','' }
  757. #                    no section of this type: false
  758. #                    read:    { 0,"{current}K","{current}K",string }
  759. #                    set:    { 0,"{previous}K","{new}K",string }
  760. #                    bad command: { -1,"{current}K","{current}K",string }
  761. #    Examples:        @@();
  762. #    Assumptions:    None
  763. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  764. #    History:
  765. #        01/23/93    SBR        Created
  766. #        09/27/96    BRL/MSO    Added SPEC exception handling
  767. #        03/20/97    SBR        Changed v_level to 4.
  768. #                            Use previously calculated left-top value.
  769. #                            Special-case size location for 8.0.
  770. #########################################################################
  771. Task memoryCP_setDiskCache( newDC := 'read', v_level := 4 )
  772. begin
  773.     global gmcp;
  774.     symbolicValue := '';
  775.  
  776.     if not newDC 
  777.         return {0,'','',''};
  778.     RStatus("memoryCP_setDiskCache with newDC = {newDC}",v_level);
  779.  
  780.     memoryCP_getWindowItems();
  781.     dcList := assoc('dc', gmcp);
  782.     
  783.     dcLT := dcList[1];                # Left Top of Disk Cache section in global coordinates
  784.     move_mouse({'absolute',dcLT});    # Indicate current section to human
  785.  
  786.     dcValues := { 32,64,96,128, 192,256, 384,512, 768,1024,1536,2048,2560,3072,3584,
  787.                     4096,4608,5120,5632,6144,6656,7168,7680 };
  788.     numVals := card dcValues;
  789.  
  790.     tSys := _Match([system]).v;
  791.     if (tSys ~= /7≈/)
  792.     begin
  793.         # 7.x has the "old correct" dcSizeOffset.
  794.         dcSizeOffset := { 283,17 };
  795.     end;
  796.     else
  797.     begin
  798.         # 8.0 has the "new correct" dcSizeOffset.
  799.         dcSizeOffset := { 284,17 };
  800.     end;
  801.  
  802. #        dcIconLT := offset_list( dcLT, { 15,10 } );        # section icon Left Top (do not delete this line)
  803.     dcUp :=     offset_list( dcLT, { 335,17 } );    # up arrow
  804.     dcDown :=     offset_list( dcLT, { 335,27 } );    # down arrow
  805.     dcSizeLT := offset_list( dcLT, dcSizeOffset );    # cache size 1st char Left Top
  806.  
  807.     oldDC := readGeneva9Number(dcSizeLT);
  808.     oldDCRtnVal := "{oldDC}K";
  809.     
  810.     if newDC = 'read'
  811.         return {0, oldDCRtnVal, oldDCRtnVal, "Current Disk Cache size is {oldDCRtnVal}"};
  812.     else if newDC = 'random'
  813.     begin
  814.         symbolicValue := " ({newDC})";
  815.         newDC := dcValues[random(1,card dcValues)];        #need better algorithm
  816.     end;
  817.     else begin
  818.         lastChar := card newDC;
  819.         theNum := '';
  820.         for i := 1 to lastChar - 1
  821.             theNum := theNum + newDC[i];
  822.         theNum := strToNum(theNum);
  823.         if newDC[lastChar] = 'K' and theNum > 0
  824.             newDC := theNum;
  825.         else begin
  826.             return {-1, oldDCRtnVal, oldDCRtnVal, 
  827.                 "memoryCP_setDiskCache: bad command: '{newDC}'."};
  828.         end;
  829.     end;
  830.  
  831.     originalNewDC := newDC;
  832.     newSizeIndex := isMember(newDC, dcValues);    # get index for new size
  833.     if not newSizeIndex            #condition desired size to the next lower size in the list
  834.     begin
  835.         hopeDCSize := newDC;
  836.         if hopeDCSize < dcValues[1] 
  837.             newDC := dcValues[1];
  838.         else if hopeDCSize > dcValues[numVals]
  839.             newDC := dcValues[numVals];
  840.         else begin
  841.             i := 1;
  842.             done := false;
  843.             while not done
  844.             begin
  845.                 if newDC < dcValues[i]
  846.                 begin
  847.                     done := true;
  848.                     newDC := dcValues[i - 1];
  849.                 end;
  850.                 else i := i + 1;
  851.             end;
  852.         end;
  853.         newSizeIndex := isMember(newDC, dcValues);    # redo with conditioned value
  854.     end;
  855.     oldSizeIndex := isMember(oldDC, dcValues);        # get index for old size        
  856.     numClicks := newSizeIndex - oldSizeIndex;
  857.     if numClicks < 0
  858.     begin
  859.         _Move('a', dcDown);
  860.         numClicks := 0 - numClicks;
  861.     end;
  862.     else 
  863.         _Move('a', dcUp);
  864.     
  865.     for i := 1 to (numClicks / 10)            #click slow so target won't lose events
  866.     begin
  867.         for j := 1 to 10
  868.             _Click();
  869.         wait(1);
  870.         numClicks := numClicks - 10;
  871.     end;
  872.     for j := 1 to numClicks
  873.         _Click();
  874.     
  875.     realDCSize := readGeneva9Number(dcSizeLT);
  876.     returnMsg := "Set Disk Cache size to {realDCSize}K";
  877.  
  878.     if originalNewDC <> newDC
  879.         returnMsg := returnMsg + " instead of {originalNewDC}K";
  880.     return {0, oldDCRtnVal, "{realDCSize}K", "{returnMsg}{symbolicValue}."};
  881. end;
  882.  
  883.  
  884. #########################################################################
  885. #    Task            memoryCP_setModMemMgr( newMM , v_level )
  886. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  887. #    Description:    Sets the Modern Memory Manager section of the Memory CP. 
  888. #    Parameters:        newMM:        see MemoryCP()
  889. #                    v_level:    verbosity level
  890. #    Returns:        newMM contains a false value: { 0,'','','' }
  891. #                    bad command, command failed, or no section of this type: 
  892. #                            { -1,"{currentOffOn}","{currentOffOn}",string }
  893. #                    read:    { 0,"{currentOffOn}","{currentOffOn}",string }
  894. #                    set:    { 0,"{previousOffOn}","{newOffOn}",string }
  895. #    Examples:        @@();
  896. #    Assumptions:    None
  897. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  898. #    History:
  899. #        09/08/93    SBR        Created for PowerPC as memoryCP_setNewMemMgr
  900. #        03/10/95    SBR        changed from memoryCP_setNewMemMgr to memoryCP_setModMemMgr 
  901. #        09/27/96    BRL/MSO    Added SPEC exception handling
  902. #        03/20/97    SBR        Changed v_level to 4.
  903. #                            Use previously calculated left-top value.
  904. #                            Don't use VUAid to read the system heap type.
  905. #########################################################################
  906. Task memoryCP_setModMemMgr( newMM := 'read', v_level := 4 )
  907. begin
  908.     global gmcp;
  909.     symbolicValue := '';
  910.  
  911.     if not newMM 
  912.         return {0,'','',''};
  913.     RStatus("memoryCP_setModMemMgr with newMM = {newMM}",v_level);
  914.  
  915.     memoryCP_getWindowItems();
  916.     mmList := assoc('mm', gmcp);
  917.  
  918.     if mmList[3]                                # check Modern Memory Manager On button
  919.     begin
  920.         mmLT := mmList[1];                # Left Top of MMM section in global coordinates
  921.         move_mouse({'absolute',mmLT});    # Indicate current section to human
  922.     
  923.         oldMM := _Match(mmList[3]).s[1];
  924.     end;
  925.     else 
  926.     begin                                    # no Modern Memory Manager section visible
  927. #            # Examine the system heap.
  928. #            # Commented out because we don't want to read from low memory.
  929. #            heapType := VUAid('GetMemory', {'byte', VUAid('GetMemory', {'long', 678}) + 30});
  930. #            # println "HeapType: {heapType}";
  931. #            oldMM := isMember( heapType,{ 3,7 } );        # heapTypes with Modern Memory Manager On
  932.         
  933.         # If System 7.6 or 8.0, and PowerPC, assume MM is on, otherwise assume off.
  934.         oldMM := false;
  935.         tSys := _Match([system]).v;
  936.  
  937.         if (tSys ~= /7.6≈/) or (tSys ~= /8≈/)
  938.         begin
  939.             if target_processor()[1] ~= /PPC≈/
  940.                 oldMM := true;
  941.             else
  942.                 oldMM := false;
  943.         end;
  944.     end;
  945.     
  946.     if oldMM
  947.         oldMMRtnVal := "On";
  948.     else 
  949.         oldMMRtnVal := "Off";
  950.  
  951.     if newMM = 'read'
  952.         return {0, oldMMRtnVal, oldMMRtnVal, "Current Modern Memory Manager setting is {oldMMRtnVal}"};
  953.     else if newMM = 'random'
  954.     begin
  955.         symbolicValue := " ({newMM})";
  956.         newMM := { 'Off','On' }[random(1,2)];
  957.     end;
  958.     
  959.     if newMM <> oldMMRtnVal
  960.     begin
  961.         if newMM = 'On'
  962.             clickRect := mmList[3].r;
  963.         else if newMM = 'Off'
  964.             clickRect := mmList[2].r;
  965.         else 
  966.             return {-1, oldMMRtnVal, oldMMRtnVal, "memoryCP_setModMemMgr: bad command: '{newMM}'."};
  967.  
  968.         if not mmList[2]
  969.             return {-1,oldMMRtnVal, oldMMRtnVal,
  970.                 "Modern Memory Manager section is not visible; can not set it to {newMM}{symbolicValue}."};
  971.     end;
  972.     else 
  973.         return {0, oldMMRtnVal, "{newMM}", "Modern Memory Manager is already {newMM}."};
  974.     
  975.     if clickRect
  976.     begin
  977.         _Move('a', centerOf(clickRect));        # reach out and touch someone
  978.         _Click();
  979.         if newMM = 'On' and not _Match(mmList[3]).s[1] or 
  980.                 newMM = 'Off' and not _Match(mmList[2]).s[1]
  981.             return {-1, oldMMRtnVal, oldMMRtnVal, "Attempt to set Modern Memory Manager to {newMM} failed."};    
  982.     end;
  983.     
  984.     return {0, oldMMRtnVal, "{newMM}", "Set Modern Memory Manager to {newMM}{symbolicValue}."};
  985. end;
  986.  
  987.  
  988. #########################################################################
  989. #    Task            memoryCP_setVM( vmParams, (*previousVM,*) v_level )
  990. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  991. #    Description:    Sets the Virtual Memory section of the Memory CP. 
  992. #    Parameters:        vmParams:    see MemoryCP()
  993. #                    previousVM:    when changing from 32-Bit mode to 24-Bit mode, the VM value 
  994. #                                is truncated at around 13MB if it is higher than the maximum
  995. #                                allowable value in 24-bit mode on that machine (including 
  996. #                                NuBus cards). Obviously, this is not the "real" previous 
  997. #                                value. To make sure we can return the real one, the main 
  998. #                                task, MemoryCP, reads the VM value, sets the 32-Bit section, 
  999. #                                then sets the VM section, feeding the previous VM value in 
  1000. #                                through previousVM. It's gross but it should work reliably.
  1001. #                                (removed previous VM, see below).
  1002. #                    v_level:    verbosity level
  1003. #    Returns:        vmParams contains a false value: { 0,'','','' }
  1004. #                    no section of this type: false
  1005. #                    bad command: { -1,"{currentVM}","{currentVM}",string }
  1006. #                    set failed: { -1,"{previousVM}","{newVM}",string }
  1007. #                    read:    { 0,"{currentVM}","{currentVM}",string }
  1008. #                    set:    { 0,"{previousVM}","{newVM}",string }
  1009. #                    Off:    { 0,"{previousVM}","Off",string }
  1010. #                    Too much RAM in 24-Bit: {0, oldVMRtnVal, oldVMRtnVal, string};
  1011. #    Examples:        memoryCP_setVM( { '75%' },2 );    (set to 75% of maximum, verbosity 2)
  1012. #                    memoryCP_setVM( '23M' );        (set to 23M)
  1013. #                    memoryCP_setVM( '0' );            (turn Off)
  1014. #    Assumptions:    None
  1015. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1016. #    History:
  1017. #        01/23/93    SBR        Created
  1018. #        03/13/93    SBR        Removed previousVM because it is too gross. This function 
  1019. #                            should return the same value if called from the main task
  1020. #                            or called seperately.
  1021. #        09/27/96    BRL/MSO    Added SPEC exception handling
  1022. #        03/20/97    SBR        Changed v_level to 4.
  1023. #                            Use previously calculated left-top value.
  1024. #                            Special-case item locations for 8.0.
  1025. #                            Use StaticText for vmSizeMax and vmBuiltIn.
  1026. #        02/23/98    SBR        Added case 48 for system 8.1.
  1027. #                            Removed cases for alpha versions of system 8.0.
  1028. #                            Increased default megsPerSecond to 50 + (megsToGo / 4).
  1029. #########################################################################
  1030. Task memoryCP_setVM( vmParams := 'read', (*previousVM := {},*) v_level := 4 )
  1031. begin
  1032.     global gmcp;
  1033.     symbolicValue := '';
  1034.  
  1035.     if not vmParams
  1036.         return {0,{},{},''};
  1037.     RStatus("memoryCP_setVM with vmParams = {vmParams}",v_level);
  1038.  
  1039.     memoryCP_getWindowItems();
  1040.     vmList := assoc('vm', gmcp);
  1041.     b32List := assoc('32', gmcp);        # Need 32-bit setting to calculate max VM size
  1042.     udList := assoc('ud', gmcp);        # need version of mcp to calculate vm offsets
  1043.  
  1044.     if typeOf(vmParams) = 'list'
  1045.     begin
  1046.         if typeOf(vmParams[2]) = 'string' begin
  1047.             newVM := vmParams[1];                    # 2nd item is backing store volume name (unique)
  1048.             newVMBSVol := vmParams[2];
  1049.         end;
  1050.     end;
  1051.     else
  1052.         newVM := vmParams;
  1053.     
  1054.     if typeOf(newVM) = 'list'
  1055.     begin
  1056.         minAutoSize := newVM[1];                # 'auto', but adjust to fit in {low, high} inclusive
  1057.         maxAutoSize := newVM[2];
  1058.         newVM := 'auto';
  1059.     end;
  1060.     else begin
  1061.         minAutoSize := 0;                # 'auto', but adjust to fit in {low, high} inclusive
  1062.         maxAutoSize := 0;
  1063.     end;
  1064.  
  1065.     if not vmList 
  1066.         return RIncomplete("Virtual Memory section is not in this window. Can not set it to '{newVM}'.");    
  1067.  
  1068.                                                     # Do not remove any lines below, even if commented
  1069.     vmLT := vmList[1];                # Left Top of VM section in global coordinates
  1070.     move_mouse({'absolute',vmLT});    # Indicate current section to human
  1071.  
  1072. #     switch (udList[2]).o #udOrdinal
  1073. #     begin
  1074. #         case 48:         # System 8.1
  1075. #         case 49:         # System 8.0
  1076. #         case 56:         # System 7.6
  1077. #         begin
  1078. #             # All GM systems thus far have the "correct" VMSizeOffset.
  1079. #             vmSizeOffset := { 285,75 };
  1080. #         end;
  1081. #             
  1082. #         default:
  1083. #         begin
  1084.             # All GM systems thus far have the "correct" VMSizeOffset.
  1085.             vmSizeOffset := { 285,75 };
  1086. #         end;
  1087. #     end;
  1088.     
  1089. #    vmIconLT :=    offset_list( vmLT, { 11,33 } );        # VM icon
  1090.     vmUp :=        offset_list( vmLT, { 335,73 } );    # VM set size up arrow
  1091.     vmDown :=    offset_list( vmLT, { 335,83 } );    # VM set size down arrow
  1092.     vmHDLT :=    offset_list( vmLT, { 299,43 } );    # VM available on disk 1st char Left Top
  1093.     vmRAMLT :=    offset_list( vmLT, { 299,56 } );    # VM available built-in memory 1st char Left Top
  1094.     vmSizeLT :=    offset_list( vmLT, vmSizeOffset );    # VM after restart size 1st char Left Top
  1095. #    vmMsgLT :=    offset_list( vmLT, { 171,73 } );    # VM after restart msg 1st char Left Top
  1096. #    vmMsgRB :=    offset_list( vmMsgLT, { 110,12 } );    # VM after restart msg 1st char Right Bottom
  1097.                                                     # Do not remove any lines above, even if commented
  1098.  
  1099. #    if previousVM begin                # took out previousVM, but maybe…
  1100. #        if typeOf(previousVM) = 'list'
  1101. #            oldVMRtnVal := previousVM[1];
  1102. #        else oldVMRtnVal := previousVM;
  1103. #    end;
  1104. #    else 
  1105. #    begin
  1106.  
  1107.         oldVM := readGeneva9Number(vmSizeLT);
  1108.         if oldVM
  1109.             oldVMRtnVal := {"{oldVM}M",''};
  1110.         else oldVMRtnVal := {'Off',''};
  1111.         
  1112. #    end;
  1113.  
  1114.     #println     'newVM: ',newVM;
  1115.     #println     'oldVMRtnVal: ',oldVMRtnVal;
  1116.     vmDisabledString := 'Virtual Memory is disabled. There is no size value to measure.';
  1117.     
  1118.     badCommand := true;            # we might not recognize this command
  1119.             
  1120.     if newVM = 'read'
  1121.         return {0, oldVMRtnVal, oldVMRtnVal, "Current VM setting is {oldVMRtnVal}"};
  1122.     else if (newVM = 'auto')
  1123.     begin
  1124.         clickVMOnButton(vmList[3]);
  1125.         _Move('a', centerOf(vmList[2].r));
  1126.         _Click();
  1127.         clickVMOnButton(vmList[3]);
  1128.         temp := readGeneva9Number(vmSizeLT);
  1129.         if temp
  1130.             tempStr := "{temp}M";
  1131.         else
  1132.             tempStr := '';
  1133.         if (not temp) or _Match(vmList[2]).s[1] or (not _Match(vmList[3]).s[1])
  1134.             return {-1, oldVMRtnVal, tempStr, 'Attempt to set Virtual Memory automatically failed.'};
  1135.         if minAutoSize and (temp < minAutoSize)
  1136.             newVM := "{minAutoSize}M";
  1137.         else if maxAutoSize and (temp > maxAutoSize)
  1138.             newVM := "{maxAutoSize}M";
  1139.         else 
  1140.             return {0, oldVMRtnVal, tempStr, "Automatically set Virtual Memory to {temp}M."};
  1141.     end;
  1142.     
  1143.     else if newVM = 'Off' or newVM = '0M' or newVM = '0%'
  1144.     begin
  1145.         _Move('a', centerOf(vmList[2].r));
  1146.         _Click();
  1147.         temp := readGeneva9Number(vmSizeLT);
  1148.         if temp 
  1149.             temp := "{temp}M";
  1150.         else 
  1151.             temp := '';
  1152.         if temp or not _Match(vmList[2]).s[1] or _Match(vmList[3]).s[1]        #something wrong
  1153.             return {-1, oldVMRtnVal, temp, 'Attempt to turn Off Virtual Memory failed.'};
  1154.         return {0, oldVMRtnVal, 'Off', 'Turned Off Virtual Memory.'};
  1155.     end;
  1156.     
  1157.     else if newVM = 'On'
  1158.     begin
  1159.         clickVMOnButton(vmList[3]);
  1160.         temp := readGeneva9Number(vmSizeLT);
  1161.         if temp
  1162.             temp := "{temp}M";
  1163.         else
  1164.             temp := '';
  1165.         if not temp or _Match(vmList[2]).s[1] or not _Match(vmList[3]).s[1]
  1166.             return {-1, oldVMRtnVal, temp, 'Attempt to turn On Virtual Memory failed.'};
  1167.         return {0, oldVMRtnVal, temp, "Turned On Virtual Memory. It was already set to {temp}."};
  1168.     end;
  1169.     
  1170.     if b32List[2]                                # first check for 32-Bit mode 'On' by the buttons
  1171.         cur32 := (_Match(b32List[3])).s[1];
  1172.     else 
  1173.     begin                                    # if no buttons then by Gestalt
  1174.         temp := _Gestalt('addr')[2];
  1175.         cur32 := temp - (temp / 2) * 2;            # if bit 1 set then 32-Bit mode, else 24-Bit mode 
  1176.     end;
  1177.  
  1178.     if cur32
  1179.     begin
  1180.         # max VM = Available on disk, when 32-bit is On
  1181.         switch (udList[2]).o #udOrdinal
  1182.         begin
  1183.             case 48:         # System 8.1
  1184.             case 49:         # System 8.0
  1185.             begin
  1186.                 # A match is faster than reading digits with VUAid, if possible.
  1187.                 try
  1188.                     match [staticText o:10 t:?vmSizeMax w:1]!;    
  1189.                 catch theError
  1190.                     ExceptionDispatcher(theError,,{"match max VM size in memoryCP_setVM", {v_level}});
  1191.                 
  1192.                 theNum := '';
  1193.                 numChars := card vmSizeMax;
  1194.                 for i := (numChars - 1) to 1 step -1
  1195.                 begin
  1196.                     theChar := vmSizeMax[i];
  1197.                     if (theChar ~= /[0-9]/)
  1198.                         theNum := theChar + theNum;
  1199.                     else
  1200.                         i := 0;
  1201.                 end;
  1202.                 vmSizeMax := strToNum(theNum);
  1203.             end;
  1204.     
  1205.             default:
  1206.             begin
  1207.                 vmSizeMax := readGeneva9Number(vmHDLT);    
  1208.             end;
  1209.         end;
  1210.         
  1211.     end;
  1212.     else
  1213.     begin
  1214.         vmSizeMax := 13;                        # otherwise max VM = 16M - 1M(ROM) - 1M(IO)
  1215.     end;
  1216.     
  1217. #        vmBuiltIn := readGeneva9Number(vmRAMLT);
  1218.     try
  1219.         match [staticText o:11 t:?vmBuiltIn w:1]!;    
  1220.     catch theError
  1221.         ExceptionDispatcher(theError,,{"match VM built-in RAM in memoryCP_setVM", {v_level}});
  1222.  
  1223.     theNum := '';
  1224.     numChars := card vmBuiltIn;
  1225.     for i := (numChars - 1) to 1 step -1
  1226.     begin
  1227.         theChar := vmBuiltIn[i];
  1228.         if (theChar ~= /[0-9]/)
  1229.             theNum := theChar + theNum;
  1230.         else
  1231.             i := 0;
  1232.     end;
  1233.     vmBuiltIn := strToNum(theNum);
  1234.  
  1235.     if vmBuiltIn > 8 and not cur32
  1236.     begin
  1237.         badVM := "The CPU has {vmBuiltIn}M built in RAM. You can not use VM in 24-bit mode";
  1238.         rdList := assoc('rd', gmcp);
  1239.         if rdList
  1240.             badVMEnd := " unless you make a RAM disk to reduce the built in RAM to below 8.";
  1241.         else badVMEnd := ".";
  1242.         return {0, oldVMRtnVal, oldVMRtnVal, badVM + badVMEnd};
  1243.     end;
  1244.         
  1245.     #println "vmBuiltIn: {vmBuiltIn}";
  1246.     vmSizeMin := 1 + vmBuiltIn;
  1247.     
  1248.     badCommand := false;                        # skip the 'xM' parsing without being a bad command
  1249.     if newVM = 'random'
  1250.     begin
  1251.         symbolicValue := " ({newVM})";
  1252.         newVM := random(vmSizeMin,vmSizeMax);
  1253.     end;
  1254.     else if newVM = 'max'
  1255.     begin
  1256.         symbolicValue := " ({newVM})";
  1257.         newVM := vmSizeMax;            
  1258.     end;
  1259.     else if newVM = 'min'
  1260.     begin
  1261.         symbolicValue := " ({newVM})";
  1262.         newVM := vmSizeMin;    
  1263.     end;
  1264.     else begin
  1265.         badCommand := true;                        # still not a good command
  1266.         lastCharIndex := card newVM;            # at this point we are parsing 'xM' or 'x%'
  1267.         lastChar := newVM[lastCharIndex];
  1268.         if lastChar = 'M' or lastChar = '%'
  1269.         begin
  1270.             theNum := '';
  1271.             for i := 1 to lastCharIndex - 1
  1272.                 theNum := theNum + newVM[i];
  1273.             theNum := strToNum(theNum);
  1274.             if not isUndefined(theNum) 
  1275.             begin
  1276.                 if theNum >= 0
  1277.                 begin
  1278.                     badCommand := false;        # we recognize the command
  1279.                     newVM := theNum;
  1280.                 end;
  1281.             end;
  1282.         end;
  1283.         if badCommand
  1284.             return {-1, oldVMRtnVal, oldVMRtnVal, "memoryCP_setVM: '{newVM}' is a bad command."};
  1285.     
  1286.         if newVM = oldVM
  1287.             return {0, oldVMRtnVal, oldVMRtnVal, "Virtual Memory was already {newVM}M."};
  1288.     
  1289.         # newVM should be a positive integer, check for bounds
  1290.         if newVM < vmSizeMin
  1291.         begin
  1292.             vmBadMsg := "{newVM}M is below minimum ({vmSizeMin}M).";
  1293.             newVM := vmSizeMin;
  1294.         end;
  1295.         else if newVM > vmSizeMax
  1296.         begin
  1297.             if cur32
  1298.             begin
  1299.                 vmBadMsg := "{newVM}M is above Available space on disk ({vmSizeMax}M).";
  1300.                 newVM := vmSizeMax;
  1301.             end;
  1302.             else begin
  1303.                 vmBadMsg := 
  1304.                     "{newVM}M is above {vmSizeMax}M, the maximum in 24-Bit mode.";
  1305.                 newVM := vmSizeMax;
  1306.             end;
  1307.         end;
  1308.     end;
  1309.  
  1310.     clickVMOnButton(vmList[3]);
  1311.  
  1312.     if oldVM
  1313.         curVMSize := oldVM;
  1314.     else
  1315.         curVMSize := readGeneva9Number(vmSizeLT);
  1316.     prevVMSize := 0;            # to check if size did not change after clicking
  1317.     #println 'newVM: ', newVM;
  1318.     #println 'curVMSize: ', curVMSize;
  1319.  
  1320.     firstTimePress := true;
  1321.     while curVMSize <> newVM and curVMSize <> prevVMSize
  1322.     begin
  1323.         prevVMSize := curVMSize;
  1324.         pressTimeActual := 0;
  1325.         pressTimeWait := 0;
  1326.         megsToGo := newVM - curVMSize;
  1327.         if megsToGo > 0 
  1328.             _Move('a', vmUp);
  1329.         else 
  1330.         begin
  1331.             _Move('a', vmDown);
  1332.             megsToGo := 0 - megsToGo;               # megsToGo must be >= 0
  1333.         end;
  1334.         
  1335.         #Initially, estimate the VM size rate of change; calculate it afterwards.
  1336.         if firstTimePress or (megsToGo < megsPerSecond)
  1337.         begin
  1338.             megsPerSecond := 50 + (megsToGo / 4);    # progressive speedup
  1339.             firstTimePress := false;
  1340.         end;
  1341.         
  1342.         if (megsToGo < megsPerSecond) or (megsToGo < 10)    # click one at a time
  1343.         begin
  1344.             maxClicks := megsPerSecond / 2;
  1345.             for i := 1 to (megsToGo / maxClicks)        # click slow so target will not lose events
  1346.             begin
  1347.                 for j := 1 to maxClicks
  1348.                     _Click();
  1349.                 wait(1);
  1350.                 megsToGo := megsToGo - maxClicks;
  1351.             end;
  1352.             for j := 1 to megsToGo
  1353.                 _Click();
  1354.         end;
  1355.         else 
  1356.         begin                # press for variable intervals
  1357.             pressTimeEst := megsToGo / megsPerSecond;
  1358.             startTime := _Match([time]);
  1359.             _PressMouse();        
  1360.             pressTimeWait := wait(pressTimeEst);
  1361.             pressTimeWait := pressTimeWait.s + 60 * pressTimeWait.m;
  1362.             _ReleaseMouse();        
  1363.             pressTimeActual := time_sub(_Match([time]), startTime);
  1364.             pressTimeActual := pressTimeActual[1] + 60 * pressTimeActual[2];
  1365.         end;
  1366.         tempVMSize := readGeneva9Number(vmSizeLT);
  1367.         if pressTimeActual
  1368.         begin
  1369.             megsPerSecond := (tempVMSize - curVMSize)/pressTimeActual;
  1370.             if megsPerSecond < 0
  1371.                 megsPerSecond := 0 - megsPerSecond;
  1372.         end;
  1373.         curVMSize := tempVMSize;
  1374.     end;    # curVMSize <> newVM and curVMSize <> prevVMSize
  1375.  
  1376.     if curVMSize = prevVMSize        # we reached an unexpected stopping point, e.g. in 24-bit mode
  1377.         vmOKMsg := "Could not reach {newVM}M{symbolicValue}. Stopped at {curVMSize}M.";
  1378.     else 
  1379.         vmOKMsg := "Set VM to {newVM}M{symbolicValue}.";
  1380.  
  1381.     if vmBadMsg  
  1382.         return {-1, oldVMRtnVal, "{curVMSize}M", "Set VM to {curVMSize}M{symbolicValue}. {vmBadMsg}"};
  1383.     else 
  1384.         return {0, oldVMRtnVal, "{curVMSize}M", vmOKMsg};
  1385. end;
  1386.  
  1387.  
  1388. #########################################################################
  1389. #    Task            memoryCP_set32Bit( new32, v_level )
  1390. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1391. #    Description:    Sets the 32-Bit Addressing section of the Memory CP. 
  1392. #    Parameters:        new32:        see MemoryCP()
  1393. #                    v_level:    verbosity level
  1394. #    Returns:        new32 contains a false value: { 0,'','','' }
  1395. #                    bad command, command failed, or no section of this type: 
  1396. #                            { -1,"{currentOffOn}","{currentOffOn}",string }
  1397. #                    read:    { 0,"{currentOffOn}","{currentOffOn}",string }
  1398. #                    set:    { 0,"{previousOffOn}","{newOffOn}",string }
  1399. #    Examples:        memoryCP_set32Bit( 'Off' );
  1400. #    Assumptions:    see MemoryCP()
  1401. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1402. #    History:
  1403. #        01/23/93    SBR        Created
  1404. #        09/27/96    BRL/MSO    Added SPEC exception handling
  1405. #        03/20/97    SBR        Changed v_level to 4.
  1406. #                            Use previously calculated left-top value.
  1407. #########################################################################
  1408. Task memoryCP_set32Bit( new32 := 'read', v_level := 4 )
  1409. begin
  1410.     global gmcp;
  1411.     symbolicValue := '';
  1412.  
  1413.     if not new32
  1414.         return {0,'','',''};
  1415.     RStatus("memoryCP_set32Bit with new32 = {new32}",v_level);
  1416.  
  1417.     memoryCP_getWindowItems();
  1418.     b32List := assoc('32', gmcp);
  1419.  
  1420.     if b32List[2]
  1421.     begin
  1422.         b32LT := b32List[1];            # Left Top of 32-bit section in global coordinates
  1423.         move_mouse({'absolute',b32LT});    # Indicate current section to human
  1424.  
  1425.         old32 := _Match(b32List[3]).s[1];
  1426.     end;
  1427.     else
  1428.     begin                                    # no 32-Bit section
  1429.         temp := _Gestalt('addr')[2];
  1430.         old32 := temp - (temp / 2) * 2;            # if bit 1 set then 32-Bit mode, else 24-Bit mode
  1431.     end;
  1432.     
  1433.     if old32
  1434.         old32RtnVal := 'On';
  1435.     else
  1436.         old32RtnVal := 'Off';
  1437.  
  1438.     if new32 = 'read'
  1439.         return {0, old32RtnVal, old32RtnVal, "Current 32-Bit setting is {old32RtnVal}"};
  1440.     else if new32 = 'random'
  1441.     begin
  1442.         symbolicValue := " ({new32})";
  1443.         new32 := { 'Off','On' }[random(1,2)];
  1444.     end;
  1445.     
  1446.     if new32 <> old32RtnVal
  1447.     begin
  1448.         if new32 = 'On'
  1449.             clickRect := b32List[3].r;
  1450.         else if new32 = 'Off'
  1451.             clickRect := b32List[2].r;
  1452.         else 
  1453.             return {-1, old32RtnVal, old32RtnVal, "memoryCP_set32Bit: bad command: '{new32}'."};
  1454.  
  1455.         if not b32List[2]
  1456.             return {-1,old32RtnVal, old32RtnVal,
  1457.                 "32-Bit section was not visible; could not set it to {new32}{symbolicValue}."};
  1458.     end;
  1459.     else 
  1460.         return {0, old32RtnVal, "{new32}", "32-Bit was already {new32}{symbolicValue}."};
  1461.     
  1462.     if clickRect
  1463.     begin
  1464.         _Move('a', centerOf(clickRect));        # reach out and touch someone
  1465.         _Click();
  1466.         if new32 = 'On' and not _Match(b32List[3]).s[1] or 
  1467.                 new32 = 'Off' and not _Match(b32List[2]).s[1]
  1468.             return {-1, old32RtnVal, old32RtnVal, "Attempt to set 32-Bit to {new32} failed."};    
  1469.     end;
  1470.     
  1471.     return {0, old32RtnVal, "{new32}", "Set 32-Bit to {new32}{symbolicValue}."};
  1472. end;
  1473.  
  1474.  
  1475. #########################################################################
  1476. #    Task            memoryCP_setRAMDisk( newRD, v_level )
  1477. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1478. #    Description:    Sets the RAM Disk section of the Memory CP. 
  1479. #    Parameters:        newRD:        see MemoryCP()
  1480. #                    v_level:    verbosity level
  1481. #    Returns:        newRD contains a false value: { 0,'','','' }
  1482. #                    no section of this type: false
  1483. #                    bad command, command failed: 
  1484. #                            { -1,"{currentRamDisk}","{currentRamDisk}",string }
  1485. #                    set failed: { -1,"{previousRamDisk}","{newRamDisk}",string }
  1486. #                    read:    { 0,"{currentRamDisk}","{currentRamDisk}",string }
  1487. #                    set:    { 0,"{previousRamDisk}","{newRamDisk}",string }
  1488. #                    Off:    { 0,"{previousRamDisk}","Off",string }
  1489. #    Examples:        memoryCP_setRAMDisk( '33%',2 );    (set to 33% of maximum, verbosity 2)
  1490. #                    memoryCP_setRAMDisk( '12348K' );    (set to 12348K)
  1491. #                    memoryCP_setRAMDisk( '0ff' );        (turn Off, do not return previous size)
  1492. #    Assumptions:    see MemoryCP()
  1493. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1494. #    History:
  1495. #        01/23/93    SBR        Created
  1496. #        06/25/93    SBR        Uses returnString = true for ReadGeneva9Numbers()
  1497. #        09/14/94    SBR        Switched to VU 2.1 with genuine long integers
  1498. #        09/27/96    BRL/MSO    Added SPEC exception handling
  1499. #        03/20/97    SBR        Changed v_level to 4.
  1500. #                            Use previously calculated left-top value.
  1501. #                            Special-case item locations for 8.0.
  1502. #        02/23/98    SBR        Added case 48 for system 8.1.
  1503. #                            Removed cases for alpha versions of system 8.0.
  1504. #########################################################################
  1505. Task memoryCP_setRAMDisk( newRD := 'read', v_level := 4 )
  1506. begin
  1507.     global gmcp, gRDSizeMin, gRDSizeMax;
  1508.         
  1509.     sliderWait := 200;        # milliseconds to wait when sliding 
  1510.     if not newRD
  1511.         return {0,'','',''};
  1512.     RStatus("memoryCP_setRAMDisk with newRD = {newRD}", v_level);
  1513.  
  1514.     memoryCP_getWindowItems();
  1515.     rdList := assoc('rd', gmcp);
  1516.     udList := assoc('ud', gmcp);    # need version of mcp to calculate rd offsets
  1517.  
  1518.     if not rdList 
  1519.         return RIncomplete("RAM Disk section is not in this window. Can not set it to '{newRD}'.");    
  1520.  
  1521.     rdLT := rdList[1];                # Left Top of RAM Disk section in global coordinates
  1522.     move_mouse({'absolute',rdLT});    # Indicate current section to human
  1523.  
  1524. #        rdKnobRect := offset_list( rdLT, { 197,61,212,79 } );    # slider knob rectangle, max RAM disk
  1525. #        rdKnobRect := offset_list( rdLT, { 165,29,180,46 } );    # slider knob rectangle, min RAM disk
  1526.  
  1527. #    before comparing. VU 2.1 detects this offset and corrects for it internally.
  1528. #    
  1529.     switch (udList[2]).o #udOrdinal
  1530.     begin
  1531.         case 48:         # System 8.1
  1532.         case 49:         # System 8.0
  1533.         begin
  1534.             # Post 8.0 has the "new correct" dcSizeOffset.
  1535.             rdSizeOffset := { 272,66 };
  1536.         
  1537.             rdSliderMinOffset := { 183,34 };
  1538.             rdSliderMaxOffset := { 302,34 };
  1539.         end;
  1540.  
  1541.         case 56:         # System 7.6
  1542.         begin
  1543.             rdSizeOffset := { 271,66 };
  1544.             rdSliderMinOffset := { 180,38 };
  1545.             rdSliderMaxOffset := { 305,38 };
  1546.         end;
  1547.  
  1548.         default:
  1549.         begin
  1550.             rdSizeOffset := { 273,66 };
  1551.             rdSliderMinOffset := { 172,38 };
  1552.             rdSliderMaxOffset := { 297,38 };
  1553.         end;
  1554.     end;
  1555.     
  1556.     rdSizeLT := offset_list( rdLT, rdSizeOffset );            # left top of first digit in size box
  1557.     rdSliderMin := offset_list( rdLT, rdSliderMinOffset );    # center of slider, min RAM disk
  1558.     rdSliderMax := offset_list( rdLT, rdSliderMaxOffset );    # center slider, max RAM disk
  1559.     rdPixel := { 0,rdSliderMax[1] - rdSliderMin[1] };        # {pixel position, total possible}
  1560.  
  1561.     oldRD := readGeneva9Number(rdSizeLT);
  1562.     if oldRD
  1563.         oldRDRtnVal := "{oldRD}K";
  1564.     else 
  1565.         oldRDRtnVal := 'Off';
  1566.     
  1567.     rdEnabled := _Match(rdList[4]).e;        #check for On button enabled (RAM Disk empty or Off)
  1568.     rdDisabledString := "RAM Disk controls are disabled. Current size is {oldRDRtnVal}.";
  1569.     
  1570.     if isMember(newRD, { 'Off','0K','0%','0%!' })
  1571.     begin
  1572.         rdValueAfterTurningOff := 0;
  1573.         if oldRD = 0
  1574.             offMsg := 'RAM Disk was already Off.';
  1575.         else
  1576.         begin
  1577.             if not rdEnabled
  1578.                 return {-1, oldRDRtnVal, oldRDRtnVal, rdDisabledString};
  1579.             _Move('a', centerOf(rdList[3].r));
  1580.             _Click();                                # click the Off button
  1581.             rdValueAfterTurningOff := readGeneva9Number(rdSizeLT);
  1582.             offMsg := 'Turned Off RAM Disk.';
  1583.         end;
  1584.  
  1585.         if rdValueAfterTurningOff
  1586.             rdValueAfterTurningOff := "{temp}K";
  1587.         else
  1588.             rdValueAfterTurningOff := '';
  1589.             
  1590.         if ( rdValueAfterTurningOff or                 # non-zero value or buttons wrong
  1591.                 ( not _Match(rdList[3]).s[1]) or _Match(rdList[4]).s[1] )
  1592.             return {-1, oldRDRtnVal, temp, 'Attempt to turn Off RAM Disk failed.'};
  1593.         return {0, oldRDRtnVal, 'Off', offMsg};
  1594.     end;
  1595.  
  1596.     badCommand := true;            # we might not recognize this command
  1597.         
  1598.     lastChar := newRD[card newRD];
  1599.     setByK := lastChar = 'K';
  1600.     setByPixPercent := lastChar = '%';
  1601.     setByKPercent := newRD[(card newRD) - 1] = '%' and lastChar = '!';
  1602.  
  1603.     if setByK or setByPixPercent or setByKPercent    # normal path to set rd to a value
  1604.     begin 
  1605.         theNum := '';
  1606.         if setByKPercent
  1607.             tossOut := 2;                            # remove '%!' at the end
  1608.         else
  1609.             tossOut := 1;                            # remove '%' or 'K' at the end
  1610.         for i := 1 to (card newRD) - tossOut
  1611.             theNum := theNum + newRD[i];
  1612.         theNum := strToNum(theNum);
  1613.         
  1614.         if theNum >= 0 
  1615.         begin
  1616.             if ((setByPixPercent or setByKPercent) and theNum <= 100) or setByK
  1617.             begin
  1618.                 badCommand := false;                # we recognize the command
  1619.                 newRD := theNum;
  1620.                 if newRD = oldRD
  1621.                     return {0, oldRDRtnVal, oldRDRtnVal, "RAM Disk is already {newRD}K."};
  1622.             end;
  1623.             else
  1624.                 setByPixPercent := false;
  1625.         end;
  1626.     end;
  1627.  
  1628.     if newRD = 'read'
  1629.         return {0, oldRDRtnVal, oldRDRtnVal, "Current RAM Disk size is {oldRDRtnVal}."};
  1630.     
  1631.     newRDPixMethod := isMember(newRD, {'random','min','max'});
  1632.     if newRDPixMethod or setByPixPercent
  1633.     begin
  1634.         # We do all of these methods by moving the slider in units of pixels
  1635.         # Off has same likelihood as other settings
  1636.         switch newRDPixMethod
  1637.         begin
  1638.             case 0:                                             # setByPixPercent
  1639.                 thePixel := 1 + (newRD * rdPixel[2]) / 100;    
  1640.             case 1:                                            # newRD = 'random'
  1641.                 thePixel := random(0,rdPixel[2] + 1);
  1642.             case 2:                                            # newRD = 'max'
  1643.                 thePixel := rdPixel[2] + 1;            
  1644.             case 3:                                            # newRD = 'min'
  1645.                 thePixel := 1;            
  1646.         end;
  1647.         
  1648.         if not rdEnabled 
  1649.             return {-1, oldRDRtnVal, oldRDRtnVal, rdDisabledString};
  1650.         
  1651.         _Move('a', centerOf(rdList[3].r));    # turn RAM Disk Off first
  1652.         _Click();
  1653.         if thePixel > 0                        # leave it Off if random chooses zero
  1654.         begin
  1655.             _Move('a', centerOf(rdList[4].r));
  1656.             _Click();
  1657.             _Move('a', rdSliderMin);
  1658.             wait(0,0,0,sliderWait);
  1659.             _PressMouse();        
  1660.             wait(0,0,0,sliderWait);
  1661.             _Move('r', { thePixel - 1,0 });
  1662.             wait(0,0,0,sliderWait);
  1663.             _ReleaseMouse();        
  1664.         end;
  1665.         rdSettingByPixel := readGeneva9Number(rdSizeLT);
  1666.         if setByPixPercent
  1667.             strEnd := "% by pixel";
  1668.         else
  1669.             strEnd := '';
  1670.         return {0, oldRDRtnVal, 
  1671.                 "{rdSettingByPixel}K", "Set RAM Disk to {rdSettingByPixel}K ({newRD}{strEnd})."};
  1672.     end;    
  1673.     
  1674.     if badCommand        # if we reached here then newRD is a bad command
  1675.         return {-1, oldRDRtnVal, oldRDRtnVal, "memoryCP_setRAMDisk: '{newRD}' is a bad command."};
  1676.  
  1677.     if not rdEnabled 
  1678.         return {-1, oldRDRtnVal, oldRDRtnVal, rdDisabledString};
  1679.  
  1680.     clickAt := {rdList[3].r, rdList[4].r};                # turn Off then On, now it's at minimum
  1681.     for each at in clickAt
  1682.     begin
  1683.         _Move('a', centerOf(at));
  1684.         _Click();
  1685.     end;
  1686.  
  1687.     if isUndefined(gRDSizeMin)
  1688.         gRDSizeMin := readGeneva9Number(rdSizeLT);        # read minimum RAM disk size
  1689.     
  1690.     if (newRD < gRDSizeMin) and setByK
  1691.         return {-1, oldRDRtnVal, "{gRDSizeMin}K",
  1692.             "New size ({newRD}K) was below minimum ({gRDSizeMin}K). Used minimum size."};
  1693.     
  1694.     _Move('a', rdSliderMin);
  1695.     wait(0,0,0,sliderWait);
  1696.     _PressMouse();        
  1697.     wait(0,0,0,sliderWait);
  1698.     _Move('a', rdSliderMax);
  1699.     wait(0,0,0,sliderWait);
  1700.     _ReleaseMouse();        
  1701.  
  1702.     if isUndefined(gRDSizeMax)
  1703.         gRDSizeMax := readGeneva9Number(rdSizeLT);        # read maximum RAM disk size
  1704.     
  1705.     if newRD > gRDSizeMax
  1706.         return {-1, oldRDRtnVal, "{gRDSizeMax}K",
  1707.             "New size ({newRD}) was above maximum ({gRDSizeMax}). Used maximum size."};
  1708.  
  1709.     rdSizeAttempt := newRD;        # If we get here we are going to set RD to a specific value
  1710.     
  1711.     spread := gRDSizeMax - gRDSizeMin;
  1712.     if setByKPercent
  1713.     begin
  1714.         rdSizeAttempt := newRD * spread;
  1715.         rdSizeAttempt := rdSizeAttempt / 100;
  1716.         rdSizeAttempt := rdSizeAttempt + gRDSizeMin;
  1717.     end;
  1718.     
  1719.     # Several println's are conditionally executed; more efficient to skip if not executed
  1720.     printIt := R_BeVerbose(4);    
  1721.     if printIt 
  1722.         println "rdSizeAttempt: {rdSizeAttempt}K";
  1723.  
  1724.     rdControl := _Match(rdList[2]).s;
  1725.  
  1726.     if printIt 
  1727.         println "rdControl: {rdControl}";
  1728.  
  1729.     if rdControl[1] < rdControl[2]            # adjust control max to physically possible max
  1730.         rdControlMax := rdControl[1];        # for smooth calculating later
  1731.     else 
  1732.         rdControlMax := rdControl[2];
  1733.  
  1734.     if printIt 
  1735.         println "rdControlMax: {rdControlMax}";
  1736.  
  1737.     # set to closest value <= requested size
  1738.     if printIt 
  1739.         println "spread (max - min): {spread}K";
  1740.     sizeStep := spread / rdControlMax;
  1741.     if printIt 
  1742.         println "sizeStep: {sizeStep}";
  1743.     wantMin := rdSizeAttempt - gRDSizeMin;
  1744.     if printIt 
  1745.         println "wantMin: {wantMin}";
  1746.     pixelValue := wantMin / sizeStep;
  1747.     if printIt 
  1748.         println "pixelValue: {pixelValue}";
  1749.     pixelValue := pixelValue * 10 + 9;        # insert fudge factor
  1750.     if printIt 
  1751.         println "pixelValue: {pixelValue}";
  1752.     pixelValue := pixelValue * rdPixel[2];
  1753.     if printIt 
  1754.         println "pixelValue: {pixelValue}";
  1755.     pixelValue := pixelValue / rdControlMax;
  1756.     if printIt 
  1757.         println "pixelValue: {pixelValue}";
  1758.     pixelValue := pixelValue / 10;            # remove fudge factor
  1759.     if printIt 
  1760.         println "pixelValue: {pixelValue}";
  1761.  
  1762.     nextHigher := (pixelValue + 1) * rdControlMax;
  1763.     if printIt 
  1764.         println "nextHigher: {nextHigher}";
  1765.     nextHigher := nextHigher / rdPixel[2];
  1766.     if printIt 
  1767.         println "nextHigher: {nextHigher}";
  1768.     nextHigher := nextHigher * sizeStep;
  1769.     if printIt 
  1770.         println "nextHigher: {nextHigher}";
  1771.     nextHigher := gRDSizeMin + nextHigher;
  1772.     if printIt 
  1773.         println "nextHigher: {nextHigher}";
  1774.  
  1775.     _PressMouse();        
  1776.     wait(0,0,0,sliderWait);
  1777.     _Move('r', { pixelValue - rdPixel[2],0 });
  1778.     wait(0,0,0,sliderWait);
  1779.     _ReleaseMouse();        
  1780.     curRDSize := readGeneva9Number(rdSizeLT);
  1781.     if nextHigher = curRDSize
  1782.     begin
  1783.         RStatus('RAM Disk pixel value could have been larger!?',4);
  1784.         RStatus("RAM Disk ended up at {curRDSize}K, but script was aiming at {rdSizeAttempt}K",1);
  1785.     end;
  1786.  
  1787.     if nextHigher < curRDSize
  1788.     begin
  1789.         RStatus('RAM Disk value was set to large!? ',1);
  1790.         RStatus("RAM Disk ended up at {curRDSize}K, but script was aiming at {rdSizeAttempt}K",1);
  1791.     end;
  1792.     else if setByK and (curRDSize <> rdSizeAttempt)
  1793.         returnMsgEnd := " instead of {rdSizeAttempt}K";
  1794.     else 
  1795.         returnMsgEnd := '';
  1796.         
  1797.     if setByKPercent
  1798.         returnMsgEnd := " ({newRD}% by value; {newRD}% of {gRDSizeMin}-{gRDSizeMax} is {rdSizeAttempt}K)";
  1799.     return {0, oldRDRtnVal, "{curRDSize}K", "Set RAM Disk to {curRDSize}K{returnMsgEnd}."};
  1800. end;                #memoryCP_setRAMDisk()
  1801.  
  1802.  
  1803. #########################################################################
  1804. #    Task            memoryCP_setUseDefaults( newUD, v_level )
  1805. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1806. #    Description:    Clicks Use Defaults button in the Memory CP. 
  1807. #    Parameters:        newUD:        see MemoryCP()
  1808. #                    v_level:    verbosity level
  1809. #    Returns:        newUD contains a false value: { 0,'','','' }
  1810. #                    Use Defaults button is absent or disabled: 
  1811. #                            { -1, {}, {}, string }
  1812. #                    click:    { 0, 'click', 'click', string }
  1813. #    Examples:        memoryCP_setUseDefaults( 'click' );
  1814. #    Assumptions:    see MemoryCP()
  1815. #∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞
  1816. #    History:
  1817. #        02/11/93    SBR        Created
  1818. #        03/20/97    SBR        Changed v_level to 4.
  1819. #                            Use previously calculated left-top value.
  1820. #########################################################################
  1821. Task memoryCP_setUseDefaults( newUD := 'click', v_level := 4 )
  1822. begin
  1823.     global gmcp;
  1824.     symbolicValue := '';
  1825.  
  1826.     if not newUD 
  1827.         return {0,'','',''};
  1828.     RStatus("memoryCP_setUseDefaults with newUD = {newUD}",v_level);
  1829.  
  1830.     memoryCP_getWindowItems();
  1831.     udList := assoc('ud', gmcp);
  1832.  
  1833.     udLT := udList[1];                # Left Top of Use Defaults section in global coordinates
  1834.     move_mouse({'absolute',udLT});    # Indicate current section to human
  1835.  
  1836.     if newUD = 'click'
  1837.     begin
  1838.         if _MatchBoolean([button t:'Use Defaults'])
  1839.         begin
  1840.             _Move('a', centerOf(udList[2].r) );
  1841.             _Click();
  1842.             return {0, 'click', 'click', 'Clicked Use Defaults button.'};
  1843.         end;
  1844.         else 
  1845.             return {-1, {}, {}, 'The Use Defaults button was absent or disabled.'};
  1846.     end;
  1847. end;
  1848.  
  1849.  
  1850. #########################################################################
  1851. #    Task            clickVMOnButton( vmOnButton, v_level )
  1852. #    Description:    Clicks the On button in the Virtual Memory section of 
  1853. #                    the Memory CP. Handles PowerBook battery message. The
  1854. #                    descriptor is used because the buttons are offset -89.
  1855. #                    It is a constructed descriptor, not from a match.
  1856. #    Parameters:        vmOnButton:    the descriptor for the VM On button
  1857. #                    v_level:    verbosity level
  1858. #    Returns:        nothing
  1859. #    History:
  1860. #        01/23/93    SBR        Created for use with memoryCP_setVM
  1861. #        09/27/96    BRL/MSO    Added SPEC exception handling
  1862. #########################################################################
  1863. Task clickVMOnButton( vmOnButton, v_level := 5 )
  1864. begin
  1865.     RStatus("clickVMOnButton with vmOnButton = {vmOnButton}",v_level);
  1866.     _Move('a', centerOf(vmOnButton.r) );
  1867.     _Click();
  1868.     wait(1);
  1869.     if _MatchBoolean([staticText t:/Using V≈M≈will reduce your battery life./ w:1], false)
  1870.     begin
  1871.         _Select([button]);
  1872.         while not _MatchBoolean( [window t:'Memory' o:1], true)
  1873.             wait(1);
  1874.     end;
  1875. end;
  1876.  
  1877.  
  1878. #########################################################################
  1879. #    Task            centerOf( r, v_level )
  1880. #    Description:    Returns the point in the center of rectangle r.    
  1881. #    Parameters:        r:            { Left,Top,Bottom,Right }
  1882. #                    v_level:    verbosity level
  1883. #    Returns:        nothing
  1884. #    History:
  1885. #        01/23/93    SBR        Created for use with memoryCP_setVM
  1886. #########################################################################
  1887. task centerOf( r := {0,0,0,0}, v_level := 5 )
  1888. begin
  1889.     RStatus("centerOf with r = {r}",v_level);
  1890.     return { (r[1] + r[3]) / 2 , (r[2] + r[4]) / 2 };
  1891. end;
  1892.